﻿
using Xacml.Core;
using Xacml.Core.Policy;
using Xacml.Core.Runtime;
using System.Collections;
using System.Xml;

namespace Xacml.Core.Context
{
  public class AttributeElementReadWrite : StringValueBase
  {
    private AttributeValueElementCollectionReadWrite _attributeValues = new AttributeValueElementCollectionReadWrite();
    private string _attributeId;
    private string _dataType;
    private string _issuer;
    private string _issueInstant;

    public virtual string AttributeId
    {
      get
      {
        return this._attributeId;
      }
      set
      {
        this._attributeId = value;
      }
    }

    public virtual string DataType
    {
      get
      {
        return this._dataType;
      }
      set
      {
        this._dataType = value;
      }
    }

    public virtual string Issuer
    {
      get
      {
        return this._issuer;
      }
      set
      {
        this._issuer = value;
      }
    }

    public virtual string IssueInstant
    {
      get
      {
        return this._issueInstant;
      }
      set
      {
        this._issueInstant = value;
      }
    }

    public virtual AttributeValueElementCollectionReadWrite AttributeValues
    {
      get
      {
        return this._attributeValues;
      }
      set
      {
        this._attributeValues = value;
      }
    }

    public override string Value
    {
      get
      {
        if (this.SchemaVersion == XacmlVersion.Version10 || this.SchemaVersion == XacmlVersion.Version11 || this._attributeValues.Count <= 1)
          return this._attributeValues[0].Contents;
        throw new EvaluationException("there is more than one value.");
      }
      set
      {
        this._attributeValues[0].Contents = value;
      }
    }

    public override string DataTypeValue
    {
      get
      {
        return this._dataType;
      }
      set
      {
        this._dataType = value;
      }
    }

    public override bool IsReadOnly
    {
      get
      {
        return false;
      }
    }

    public AttributeElementReadWrite(string attributeId, string dataType, string issuer, string issueInstant, string value, XacmlVersion schemaVersion)
      : base(XacmlSchema.Context, schemaVersion)
    {
      this._attributeId = attributeId;
      this._dataType = dataType;
      this._issuer = issuer;
      this._issueInstant = issueInstant;
      this._attributeValues.Add(new AttributeValueElementReadWrite(value, schemaVersion));
    }

    public AttributeElementReadWrite(AttributeElementReadWrite attributeElement)
      : base(XacmlSchema.Context, attributeElement.SchemaVersion)
    {
      this._attributeId = attributeElement._attributeId;
      this._dataType = attributeElement._dataType;
      this._issuer = attributeElement._issuer;
      this._issueInstant = attributeElement._issueInstant;
      foreach (AttributeValueElementReadWrite attributeValueElement in (CollectionBase) attributeElement._attributeValues)
        this._attributeValues.Add(new AttributeValueElementReadWrite(attributeValueElement));
    }

    public AttributeElementReadWrite(XmlReader reader, XacmlVersion schemaVersion)
      : base(XacmlSchema.Context, schemaVersion)
    {
      if (!(reader.LocalName == "Attribute") || !this.ValidateSchema(reader, schemaVersion))
        return;
      this._attributeId = reader.GetAttribute("AttributeId");
      this._dataType = reader.GetAttribute("DataType");
      this._issuer = reader.GetAttribute("Issuer");
      if (schemaVersion == XacmlVersion.Version10 || schemaVersion == XacmlVersion.Version11)
        this._issueInstant = reader.GetAttribute("IssueInstant");
      while (reader.Read())
      {
        switch (reader.LocalName)
        {
          case "AttributeValue":
            this._attributeValues.Add(new AttributeValueElementReadWrite(reader, schemaVersion));
            break;
        }
        if (reader.LocalName == "Attribute" && reader.NodeType == XmlNodeType.EndElement)
          break;
      }
    }

    public bool Match(AttributeDesignatorBase attributeDesignator)
    {
      return this.AttributeId == attributeDesignator.AttributeId && this.DataType == attributeDesignator.DataType && (attributeDesignator.Issuer == null || attributeDesignator.Issuer.Length == 0 || this.Issuer == attributeDesignator.Issuer);
    }

    public override string ToString()
    {
      if (this.SchemaVersion == XacmlVersion.Version10 || this.SchemaVersion == XacmlVersion.Version11)
        return "[" + this._attributeId + "[" + this._dataType + "]:" + this._attributeValues[0].Contents + "]";
      return "[" + this._attributeId + "[" + this._dataType + "]:" + this._attributeValues[0].Contents + "]";
    }
  }
}
